﻿using System;
using System.Text;

using NORM.Common;
using NORM.DataBase;
using NORM.Entity;

using System.Collections.Generic;
using System.Reflection;
using System.Diagnostics;

namespace NORM.SQLObject
{
    public partial class OQL
    {
        public OQLJoin Join(EntityBase model)
        {
            OQLJoin joinentity = new OQLJoin(model);
            _join = true;            
            modelArray.Add(model);
            string t1 = string.Empty;//modelobject表的别名
            GetAsTableName(modelobject.TableName, out t1);
            string t2 = string.Empty;//model 表的别名
            GetAsTableName(model.TableName, out t2);
            this.sql += " FROM " + "[" + modelobject.TableName + "] " + t1 + " INNER JOIN [" + model.TableName + "] " + t2 + "";

            model.PropertyOnGetting += this.OnPropertyChanged;
            joinentity.mainOql = this;            
            return joinentity;
        }

        public OQLJoin LeftJoin(EntityBase model)
        {
            OQLJoin joinentity = new OQLJoin(model);
            _join = true;            
            modelArray.Add(model);
            string t1 = string.Empty;//modelobject表的别名
            GetAsTableName(modelobject.TableName, out t1);
            string t2 = string.Empty;//model 表的别名
            GetAsTableName(model.TableName, out t2);
            this.sql += " FROM " + "[" + modelobject.TableName + "] " + t1 + " LEFT JOIN [" + model.TableName + "] " + t2 + "";

            model.PropertyOnGetting += this.OnPropertyChanged;
            joinentity.mainOql = this;
            return joinentity;
        }

        public OQLJoin RightJoin(EntityBase model)
        {
            OQLJoin joinentity = new OQLJoin(model);
            _join = true;             
            modelArray.Add(model);
            string t1 = string.Empty;//modelobject表的别名
            GetAsTableName(modelobject.TableName, out t1);
            string t2 = string.Empty;//model 表的别名
            GetAsTableName(model.TableName, out t2);
            this.sql += " FROM " + "[" + modelobject.TableName + "] " + t1 + " RIGHT JOIN [" + model.TableName + "] " + t2 + "";

            model.PropertyOnGetting += this.OnPropertyChanged;
            joinentity.mainOql = this;
            return joinentity;
        }
        
        public OQL Where(object Field, object Value)
        {
            lock (Locker.instance)
            {
                List<Condition> conditions = new List<Condition>();

                try
                {
                    string fieldstring = Field + "";

                    //if (_join && this.fieldStack.Count > 0)                    
                    //{
                    //    TableField tf = this.fieldStack.Pop();
                    //    fieldstring = tf.Entity.TableName + "." + tf.Name;
                    //}

                    if (this.fieldStack.Count > 0)
                    {
                        TableField tf = this.fieldStack.Pop();
                        if (_join)
                        {
                            fieldstring = tf.Entity.TableName + "." + tf.Name;
                        }
                        else
                        {
                            fieldstring = tf.Name;
                        }
                    }

                    if (this._conditions != null)
                    {
                        foreach (Condition c in this._conditions)
                        {
                            conditions.Add(c);
                        }

                        this._conditions = null;
                        GC.Collect();
                    }
                     
                    GC.Collect();

                    Condition condition = new Condition();
                    condition.Field = fieldstring;
                    condition.Value = Value;
                    condition.Comparison = "=";

                    conditions.Add(condition);

                }
                catch (Exception ex)
                {
                    throw new NORMException(ExceptionType.OQLExceptin, ex.Message);
                }

                return Where(conditions.ToArray());
            }            
        }

        public OQL Where(object Field, string Comparison,  object Value)
        {
            lock (Locker.instance)
            {

                Condition condition = new Condition();

                try
                {
                    string fieldstring = Field + "";

                    //if (_join && this.fieldStack.Count > 0)                    
                    //{
                    //    TableField tf = this.fieldStack.Pop();
                    //    fieldstring = tf.Entity.TableName + "." + tf.Name;
                    //}

                    if (this.fieldStack.Count > 0)
                    {
                        TableField tf = this.fieldStack.Pop();
                        if (_join)
                        {
                            fieldstring = tf.Entity.TableName + "." + tf.Name;
                        }
                        else
                        {
                            fieldstring = tf.Name;
                        }
                    }

                    this._conditions = null;
                    GC.Collect();

                    condition.Field = fieldstring;
                    condition.Value = Value;
                    condition.Comparison = Comparison;
                }
                catch (Exception ex)
                {
                    throw new NORMException(ExceptionType.OQLExceptin, ex.Message);
                }
                
                return Where(new Condition[] { condition });
            }
        }

        public OQL And(object Field, object Value)
        {
            lock (Locker.instance)
            {               
                string fieldstring = Field + "";                

                List<Condition> conditions = new List<Condition>();

                try
                {
                    if (this._conditions != null)
                    {
                        foreach (Condition c in this._conditions)
                        {
                            conditions.Add(c);
                        }

                        this._conditions = null;
                        GC.Collect();
                    }

                    if (_join && this.fieldStack.Count > 0)
                    {
                        TableField tf = this.fieldStack.Pop();
                        fieldstring = tf.Entity.TableName + "." + tf.Name;
                    }

                    Condition condition = new Condition();
                    condition.Field = fieldstring;
                    condition.Value = Value;
                    conditions.Add(condition);

                }
                catch (Exception ex)
                {
                    throw new NORMException(ExceptionType.OQLExceptin, ex.Message);
                }               

                return Where(conditions.ToArray());
            }
        }

        public OQL And(object Field, string Comparison, object Value)
        {
            lock (Locker.instance)
            {
                List<Condition> conditions = new List<Condition>();

                try
                {
                    string fieldstring = Field + "";

                    if (_join && this.fieldStack.Count > 0)
                    {
                        TableField tf = this.fieldStack.Pop();
                        fieldstring = tf.Entity.TableName + "." + tf.Name;
                    }

                    if (this._conditions != null)
                    {
                        foreach (Condition c in this._conditions)
                        {
                            conditions.Add(c);
                        }

                        this._conditions = null;
                        GC.Collect();
                    }

                    Condition condition = new Condition();
                    condition.Field = fieldstring;
                    condition.Value = Value;
                    condition.Comparison = Comparison;
                    conditions.Add(condition);
                }
                catch (Exception ex)
                {
                    throw new NORMException(ExceptionType.OQLExceptin, ex.Message);
                }

                return Where(conditions.ToArray());
            }
        }

        public OQL Or(object Field, object Value)
        {
            lock (Locker.instance)
            {
                List<Condition> conditions = new List<Condition>();
                try
                {
                    string fieldstring = Field + "";

                    if (_join && this.fieldStack.Count > 0)
                    {
                        TableField tf = this.fieldStack.Pop();
                        fieldstring = tf.Entity.TableName + "." + tf.Name;
                    }                   
                    if (this._conditions != null)
                    {
                        foreach (Condition c in this._conditions)
                        {
                            conditions.Add(c);
                        }

                        this._conditions = null;
                        GC.Collect();
                    }
                    Condition condition = new Condition();
                    condition.Relation = "OR";
                    condition.Field = fieldstring;
                    condition.Value = Value;
                    conditions.Add(condition);
                }
                catch (Exception ex)
                {
                    throw new NORMException(ExceptionType.OQLExceptin, ex.Message);
                }

                return Where(conditions.ToArray());
            }
        }

        public OQL Or(object Field, string Comparison, object Value)
        {
            lock (Locker.instance)
            {
                List<Condition> conditions = new List<Condition>();

                try
                {
                    string fieldstring = Field + "";

                    if (_join && this.fieldStack.Count > 0)
                    {
                        TableField tf = this.fieldStack.Pop();
                        fieldstring = tf.Entity.TableName + "." + tf.Name;
                    }


                    if (this._conditions != null)
                    {
                        foreach (Condition c in this._conditions)
                        {
                            conditions.Add(c);
                        }

                        this._conditions = null;
                        GC.Collect();
                    }

                    Condition condition = new Condition();
                    condition.Relation = "OR";
                    condition.Field = fieldstring;
                    condition.Comparison = Comparison;
                    condition.Value = Value;
                    conditions.Add(condition);
                }
                catch (Exception ex)
                {
                    throw new NORMException(ExceptionType.OQLExceptin, ex.Message);
                }

                return Where(conditions.ToArray());
            }
        }

        public OQL In(object Field, string Value)
        {
            lock (Locker.instance)
            {
                List<Condition> conditions = new List<Condition>();

                try
                {
                    string fieldstring = Field + "";

                    if (_join && this.fieldStack.Count > 0)
                    {
                        TableField tf = this.fieldStack.Pop();
                        fieldstring = tf.Entity.TableName + "." + tf.Name;
                    }

                    if (this._conditions != null)
                    {
                        foreach (Condition c in this._conditions)
                        {
                            conditions.Add(c);
                        }

                        this._conditions = null;
                        GC.Collect();
                    }

                    Condition condition = new Condition();
                    condition.Relation = "";
                    condition.Field = fieldstring;
                    condition.Comparison = "IN";
                    condition.Value = Value;
                    conditions.Add(condition);
                }
                catch (Exception ex)
                {
                    throw new NORMException(ExceptionType.OQLExceptin, ex.Message);
                }

                return Where(conditions.ToArray());
            }
        }

        public OQL AndIn(object Field, string Value)
        {
            lock (Locker.instance)
            {
                List<Condition> conditions = new List<Condition>();

                try
                {
                    string fieldstring = Field + "";

                    if (_join && this.fieldStack.Count > 0)
                    {
                        TableField tf = this.fieldStack.Pop();
                        fieldstring = tf.Entity.TableName + "." + tf.Name;
                    }

                    if (this._conditions != null)
                    {
                        foreach (Condition c in this._conditions)
                        {
                            conditions.Add(c);
                        }

                        this._conditions = null;
                        GC.Collect();
                    }

                    Condition condition = new Condition();
                    condition.Relation = "AND";
                    condition.Field = fieldstring;
                    condition.Comparison = "IN";
                    condition.Value = Value;
                    conditions.Add(condition);
                }
                catch (Exception ex)
                {
                    throw new NORMException(ExceptionType.OQLExceptin, ex.Message);
                }

                return Where(conditions.ToArray());
            }
        }

        public OQL OrIn(object Field, string Value)
        {
            lock (Locker.instance)
            {
                List<Condition> conditions = new List<Condition>();

                try
                {
                    string fieldstring = Field + "";

                    if (_join && this.fieldStack.Count > 0)
                    {
                        TableField tf = this.fieldStack.Pop();
                        fieldstring = tf.Entity.TableName + "." + tf.Name;
                    }

                    if (this._conditions != null)
                    {
                        foreach (Condition c in this._conditions)
                        {
                            conditions.Add(c);
                        }

                        this._conditions = null;
                        GC.Collect();
                    }

                    Condition condition = new Condition();
                    condition.Relation = "OR";
                    condition.Field = fieldstring;
                    condition.Comparison = "IN";
                    condition.Value = Value;
                    conditions.Add(condition);
                }
                catch (Exception ex)
                {
                    throw new NORMException(ExceptionType.OQLExceptin, ex.Message);
                }

                return Where(conditions.ToArray());
            }
        }

    }
}
